/* libfake437 - a library for the rendering of code page 437 `graphics'
 * Copyright (C) 2008, 2009, 2010, 2011 Jack Kelly <endgame.dos@gmail.com>
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <SDL.h>
#include "fake437/types.h"
#include "fake437/primitive.h"
#include "fake437/surface.h"

F437Surface* f437_surface_new(SDL_Surface* surface,
                              const F437Font* font,
                              int scale) {
  F437Surface* result = f437_surface_try_new(surface, font, scale);
  if (result == NULL) abort();
  return result;
}

F437Surface* f437_surface_try_new(SDL_Surface* surface,
                                  const F437Font* font,
                                  int scale) {
  F437Surface* result;
  assert(surface != NULL);
  result = malloc(sizeof(*result));
  if (result == NULL) return NULL;
  result->surface = surface;
  result->font = font;
  result->scale = scale;
  result->left = (surface->w % (font->char_width * scale)) / 2;
  result->top = (surface->h % (font->char_height * scale)) / 2;
  result->width = surface->w / (font->char_width * scale);
  result->height = surface->h / (font->char_height * scale);
  result->cursor_x = result->cursor_y = 0;
  result->fg = result->bg = NULL;
  return result;
}

SDL_Surface* f437_surface_free(F437Surface* surface) {
  SDL_Surface* result;
  assert(surface != NULL);
  result = surface->surface;
  free(surface);
  return result;
}

void f437_surface_putc(F437Surface* surface, int ch) {
  assert(surface != NULL);
  assert(surface->surface != NULL);

  f437_putc(surface->surface, surface->font,
            surface->left + (surface->font->char_width
                             * surface->cursor_x
                             * surface->scale),
            surface->top + (surface->font->char_height
                            * surface->cursor_y
                            * surface->scale),
            surface->scale,
            ch, surface->fg, surface->bg);
  surface->cursor_x++;
  if (surface->cursor_x == surface->width) {
    surface->cursor_x = 0;
    surface->cursor_y = (surface->cursor_y + 1) % surface->height;
  }
}

void f437_surface_puts(F437Surface* surface, const char* str) {
  while (*str != '\0') f437_surface_putc(surface, *str++);
}

void f437_surface_fg(F437Surface* surface, const SDL_Color* fg) {
  assert(surface != NULL);
  surface->fg = fg;
}

void f437_surface_bg(F437Surface* surface, const SDL_Color* bg) {
  assert(surface != NULL);
  surface->bg = bg;
}

void f437_surface_goto_xy(F437Surface* surface, int x, int y) {
  assert(surface != NULL);
  assert(x >= 0);
  assert(x < surface->width);
  assert(y >= 0);
  assert(y < surface->height);
  surface->cursor_x = x;
  surface->cursor_y = y;
}
